package cn.kmsoft.jssc.service.impl;

import cn.kmsoft.common.utils.DateUtil;
import cn.kmsoft.common.utils.StringUtil;
import cn.kmsoft.jssc.config.AnalyseConfig;
import cn.kmsoft.jssc.entity.analyse.*;
import cn.kmsoft.jssc.entity.dlhy.DlhyEntity;
import cn.kmsoft.jssc.service.DlhyService;
import cn.kmsoft.jssc.service.ParallelAnalyseService;
import cn.kmsoft.jssc.service.SingleAnalyseService;
import cn.kmsoft.common.ResInfo;

import cn.kmsoft.stgeometry.landm.StgeoFeature;
import cn.kmsoft.stgeometry.landm.StgeoField;
import cn.kmsoft.stgeometry.util.CrsUtil;
import cn.kmsoft.stgeometry.util.GeoJson2Shapefile;
import cn.kmsoft.stgeometry.util.JTSGeometryWKTUtil;
import cn.kmsoft.wololo.object.GeoJson;
import cn.kmsoft.wololo.object.GeoJsonFeature;
import cn.kmsoft.wololo.object.GeoJsonGeometry;
import cn.kmsoft.wololo.object.query.GeoJsonQuery;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.vividsolutions.jts.geom.Geometry;
import com.vividsolutions.jts.geom.MultiPolygon;
import com.vividsolutions.jts.geom.Polygon;
import org.geotools.data.DataUtilities;
import org.geotools.data.collection.ListFeatureCollection;
import org.geotools.data.simple.SimpleFeatureCollection;
import org.geotools.feature.SchemaException;
import org.geotools.feature.simple.SimpleFeatureBuilder;
import org.geotools.geojson.feature.FeatureJSON;
import org.opengis.feature.simple.SimpleFeature;
import org.opengis.feature.simple.SimpleFeatureType;
import org.opengis.referencing.FactoryException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.File;
import java.io.IOException;
import java.io.StringWriter;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author : wangq
 * @description : todo
 * @email : cqwensten@163.com
 * @date : 2023/1/28
 */
@Service
public class DlhyServiceImpl implements DlhyService {
    private static final Logger logger = LoggerFactory.getLogger(DlhyServiceImpl.class);
    private SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss-SSS");
    private static final String defaultDlhynfStr="2021";//默认还原时间年份

    @Autowired
    private AnalyseConfig analyseConfig;

    @Autowired
    private ParallelAnalyseService parallelAnalyseService;

    @Autowired
    private SingleAnalyseService singleAnalyseService;

    @Override
    public ResInfo doPreDlhy(String projectId ){
        ResInfo resInfo = new ResInfo();

        Date dateNow = new Date();
        String dtimeNowStr = sdf.format(dateNow);


        return resInfo;
    }

    @Override
    public ResInfo doAfterDlhy(String projectId ){
        ResInfo resInfo = new ResInfo();

        Date dateNow = new Date();
        String dtimeNowStr = sdf.format(dateNow);


        return resInfo;
    }

    /**
     * 直接使用区县上报的地类图斑
     *
     * @param taskId
     * @param dlhyAnalyseParam
     * @return
     */
    public List<CustomOverlay> overlayQxsb(String taskId, DlhyAnalyseParam dlhyAnalyseParam) {

        //QXSB区县上报
        String dlhyFxlx = dlhyAnalyseParam.getType();
        System.out.println(String.format("--->overlayQxsb started,变化图斑的字段HYSJND值在2009年之前的,超出了国土变更调查数据库最低年限，直接使用区县上传地类图斑成果，dlhyFxlx: %s, taskId: %s", dlhyFxlx, taskId));

        //解析参数
        GeoJsonQuery allGeoQuery = dlhyAnalyseParam.getGeoJsonQuery();// 上传的图形
        if (allGeoQuery == null || allGeoQuery.getGeoJson() == null) {
            System.out.println(String.format("--->overlayQxsb stoped，allGeoQuery or allGeoQuery.getGeoJson is null "));
            return null;
        }
        if(StringUtil.isNullOrEmpty(taskId)) {
            taskId = UUID.randomUUID().toString();
        }

        String analyseType = allGeoQuery.getType().toString();
        String msgStr = String.format("--->overlayQxsb分析开始! taskId: %s",taskId);
        System.out.println();
        System.out.println(msgStr);

        //结果集合
        List<CustomOverlay> cusOverlayList = null;
        if (allGeoQuery.getGeoJson().trim().startsWith("{")) {
            GeoJson geoJson = (GeoJson) JSONObject.parseObject(allGeoQuery.getGeoJson(), GeoJson.class);

            cusOverlayList = new ArrayList<CustomOverlay>();
            System.out.println();
            // 3.非常重要，逐个地块进行后台空间叠加分析、面积归类汇总等操作
            List<GeoJsonFeature> feas = geoJson.getFeatures();
            int feaCount = feas.size();
            for (int i = 0; i < feaCount; i++) {
                GeoJsonFeature fea = feas.get(i);

                int xh = i+1;
                //获取TBBH信息
                Map<String, Object> feaPropers = fea.getProperties();

                //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
                Map<String,Object> feaPropsKeyLowercCase = new HashMap<>();
                feaPropers.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));

                String dkbh = feaPropsKeyLowercCase.get("tbbh") != null ? feaPropsKeyLowercCase.get("tbbh").toString() : String.valueOf(i + 10000);//TBBH
                String dlbm =  feaPropsKeyLowercCase.get("dlbm").toString() ;//DLBM
                String dlmc =  feaPropsKeyLowercCase.get("dlmc").toString() ;//DLMC
                Double djmj = StringUtil.parseDouble(feaPropsKeyLowercCase.get("djmj").toString(),"0.0") ;//DJMJ
                int dlhynf = StringUtil.parseInt(feaPropsKeyLowercCase.get("hysjnd2").toString(),"-1") ;//HYSJND2

                System.out.println();
                System.out.println(String.format("--->第 %d / %d 个地块overlayQxsb开始,地块编号：%s, 还原时间年度HYSJND2：%d", xh, feaCount, dkbh, dlhynf));

                /************* 2.上传的地块分为单个地块进行叠加 ***************/
                // 构建单个地块的Feature
                List<GeoJsonFeature> subFeas = new ArrayList<GeoJsonFeature>();
                subFeas.add(fea);

                GeoJson dkGeoJson = new GeoJson();
                dkGeoJson.setType(geoJson.getType());
                dkGeoJson.setFeatures(subFeas);
                String dkJsonStr = JSONObject.toJSONString(dkGeoJson);

                GeoJsonQuery dkQuery = new GeoJsonQuery();
                dkQuery.setDigits(allGeoQuery.getDigits());
                dkQuery.setReturnEllipsoidalArea(allGeoQuery.getReturnEllipsoidalArea());
                dkQuery.setType(allGeoQuery.getType());
                dkQuery.setWkid(allGeoQuery.getWkid());
                dkQuery.setGeoJson(dkJsonStr);

                String jobId = UUID.randomUUID().toString();
                //System.out.println(String.format("--->overlay Dlhy，DKBH: %s, DKMJ: %f, jobId: %s", dkbh, djmj, jobId));
                String msg = String.format("--->overlayQxsb, i: %d, dkbh: %s, dlbm: %s, dlmc: %s, djmj: %f, dlhynf: %d ",i, dkbh,dlbm,dlmc,djmj,dlhynf);
                System.out.println(msg);

                //分析参数组装
                AnalyseTaskParam taskParam = new AnalyseTaskParam(analyseType);
                taskParam.setJobId(jobId);
                taskParam.setTaskId(taskId);
                taskParam.setDkbh(dkbh);
                taskParam.setDkmj(djmj);
                taskParam.setQuery(dkQuery);
                taskParam.setDlhynf(dlhynf);

                CustomOverlay cusOverlay =  this.parallelAnalyseService.doDirectGeoJsonQueryConvert(analyseType,dkQuery,taskParam);
                cusOverlay.setDkbh(dkbh);
                cusOverlay.setPhase(dlhyAnalyseParam.getPhase());

                cusOverlayList.add(cusOverlay);

                System.out.println(String.format("--->第 %d / %d 个地块overlayQxsb分析完毕,地块编号：%s", xh, feaCount, dkbh));
            }

            System.out.println();
            System.out.println(String.format("--->所有地块overlayQxsb分析完成! taskId: %s",taskId));
            System.out.println();
        }

        return cusOverlayList;
    }

    /**
     * 地类还原分析： 逐个图斑（地块），按模板表数量创建线程开展还原分析
     *
     * @param taskId
     * @param dlhyAnalyseParam
     * @return
     */
    @Override
    public List<CustomOverlay> overlayDlhy(String taskId, DlhyAnalyseParam dlhyAnalyseParam) {

        String dlhyFxlx = dlhyAnalyseParam.getType();
        System.out.println(String.format("--->overlayDlhy started，dlhyFxlx: %s, taskId：%s",dlhyFxlx, taskId));

        //结果集合
        List<CustomOverlay> cusOverlayList = new ArrayList<CustomOverlay>();
        //解析参数
        GeoJsonQuery allGeoQuery = dlhyAnalyseParam.getGeoJsonQuery();// 上传的图形
        if (allGeoQuery == null || allGeoQuery.getGeoJson() == null) {
            System.out.println(String.format("--->overlayDlhy stoped，allGeoQuery or allGeoQuery.getGeoJson is null "));
            return cusOverlayList;
        }
        if(StringUtil.isNullOrEmpty(taskId)) {
            taskId = UUID.randomUUID().toString();
        }

        String analyseType = allGeoQuery.getType().toString();
        String msgStr = String.format("--->overlayDlhy,分析开始, taskId: %s",taskId);
        System.out.println();
        System.out.println(msgStr);

        if (allGeoQuery.getGeoJson().trim().startsWith("{")) {
            GeoJson geoJson = (GeoJson) JSONObject.parseObject(allGeoQuery.getGeoJson(), GeoJson.class);

            // 3.非常重要，逐个地块进行后台空间叠加分析、面积归类汇总等操作
            List<GeoJsonFeature> feas = geoJson.getFeatures();
            int feaCount = feas.size();
            for (int i = 0; i < feaCount; i++) {
                GeoJsonFeature fea = feas.get(i);

                //System.out.println();
                //获取TBBH信息
                Map<String, Object> feaPropers = fea.getProperties();

                //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
                Map<String,Object> feaPropsKeyLowercCase = new HashMap<>();
                feaPropers.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));


                String dkbh = feaPropsKeyLowercCase.get("tbbh") != null ? feaPropsKeyLowercCase.get("tbbh").toString() : String.valueOf(i+10000) ;//TBBH
                if (StringUtil.isNullOrEmpty(dkbh)) {
                    // 不参加叠加运算
                    System.out.println(String.format("--->地块编号DKBH或TBBH为空, 自动分配地块编号为：%s ","地块"+(i+1)));
                    //continue;
                }
                //还原数据年度
                String dlhyYearStr = defaultDlhynfStr;
                //变化图斑图层的还原时间年度HYSJND
                String hysjndStr = feaPropsKeyLowercCase.get("hysjnd") != null ? feaPropsKeyLowercCase.get("hysjnd").toString() : "" ;//HYSJND
                System.out.println(String.format("--->第 %d / %d 个地块overlayDlhy分析开始,地块编号：%s, 还原时间年度：%s", i + 1, feaCount, dkbh, hysjndStr));

                //变化代码BHDM
                String bhdm = feaPropsKeyLowercCase.get("bhdm") != null ? feaPropsKeyLowercCase.get("bhdm").toString() : "1";//BHDM
                if("2".equalsIgnoreCase(bhdm)){
                    //对“1与3”类型的地类图斑进行地类还原，“2”类型的图斑跳过
                    //continue;
                }

                //地块面积
                double dkmj = feaPropsKeyLowercCase.get("tbmj") != null ? Double.parseDouble(feaPropsKeyLowercCase.get("tbmj").toString()) : 0.0 ;//TBMJ

                //为了测试，新增字段，后期注释改行代码。王强 2023年2月
                //String hysjndStr2 = feaPropers.get("HYSJND2") != null ? feaPropers.get("HYSJND2").toString() : " " ;
                //用地红线范围
                //String hysjndStr = feaPropers.get("KCDJRQ") != null ? feaPropers.get("KCDJRQ").toString() : "" ;
                if(StringUtil.isNullOrEmpty(hysjndStr)){
                    System.out.println(String.format("--->该地块的还原数据年度字段HYSJND为空, 系统将默认还原到最近年度。DKBH为：%s ","地块"+dkbh));
                    //默认还原时间年度;
                    dlhyYearStr = defaultDlhynfStr;
                }else{
                    System.out.println("--->overlayDlhy, hysjndStr: "+hysjndStr);
                    try {
                        Date hysjndDate = DateUtil.parseSTDDateStr(hysjndStr);
                        dlhyYearStr = DateUtil.getYear(hysjndDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println(String.format("--->该地块的还原数据年度HYSJND：%s ",dlhyYearStr));
                //还原时间年度,正整数
                int dlhynf = Integer.parseInt(dlhyYearStr);
                if( dlhynf<=2009 ){
                    System.out.println(String.format("--->*****************************地类还原的年份小于数据库最小年份2009，统一执行2009二调标准******************************"));
                    dlhynf = 2009;
                    dlhyYearStr="2009";
                }
                //通过年份year查询找到地类还原对应的DLTB的图层名称
                AnalyseTable analyseTable = this.analyseConfig.getDltbAnalyseTableByYear( dlhyYearStr);
                if(analyseTable==null){
                    System.out.println();
                    System.out.println(String.format("--->*****************************skip overlayDlhy, taskId： %s **********************************",taskId));
                    System.out.println(String.format("--->该地块的还原数据年度HYSJND填写有误或者系统未配置对应年份的分析数据，请检查。dkbh: %s, hysjnd: %s", dkbh, dlhyYearStr));

                    continue;
                }


                /************* 2.上传的地块分为单个地块进行叠加 ***************/
                // 构建单个地块的Feature
                List<GeoJsonFeature> subFeas = new ArrayList<GeoJsonFeature>();
                subFeas.add(fea);

                GeoJson dkGeoJson = new GeoJson();
                dkGeoJson.setType(geoJson.getType());
                dkGeoJson.setFeatures(subFeas);
                String dkJsonStr = JSONObject.toJSONString(dkGeoJson);

                GeoJsonQuery dkQuery = new GeoJsonQuery();
                dkQuery.setDigits(allGeoQuery.getDigits());
                dkQuery.setReturnEllipsoidalArea(allGeoQuery.getReturnEllipsoidalArea());
                dkQuery.setType(allGeoQuery.getType());
                dkQuery.setWkid(allGeoQuery.getWkid());
                dkQuery.setGeoJson(dkJsonStr);

                String jobId = UUID.randomUUID().toString();
                //System.out.println(String.format("--->overlay Dlhy: %s，DKBH: %s, DKMJ: %f", jobId, dkbh, dkmj));

                //分析参数组装
                AnalyseTaskParam taskParam = new AnalyseTaskParam(analyseType);
                taskParam.setJobId(jobId);
                taskParam.setTaskId(taskId);
                taskParam.setDkbh(dkbh);
                taskParam.setDkmj(dkmj);
                taskParam.setQuery(dkQuery);
                taskParam.setDlhynf(dlhynf);

                List<AnalyseTable> analyseTables = new ArrayList<AnalyseTable>();
                analyseTables.add(analyseTable);

                //核心代码，提交开展分析分析结果
                CustomOverlay cusOverlay = this.parallelAnalyseService.submitOverlayCustomAnalyse(analyseType,taskParam, analyseTables);
                cusOverlay.setDkbh(dkbh);
                cusOverlay.setPhase(dlhyAnalyseParam.getPhase());

                cusOverlayList.add(cusOverlay);

                System.out.println(String.format("--->第 %d / %d 个地块overlayDlhy分析完毕,地块编号：%s", i + 1, feaCount, dkbh));
            }
            System.out.println();
            System.out.println("--->overlayDlhy,所有地块的overlayDlhy地类还原分析完成!");
            System.out.println();

        }

        return cusOverlayList;
    }


    /**
     * 逐个图斑，叠加特定年份的变更调查图层
     *
     * @param taskId
     * @param dlhyAnalyseParam
     * @return
     */
    @Override
    public List<CustomOverlay> overlayBgdc(String taskId, DlhyAnalyseParam dlhyAnalyseParam) {

        String dlhyFxlx = dlhyAnalyseParam.getType();
        System.out.println(String.format("--->overlayBgdc started，dlhyFxlx: %s, taskId: %s", dlhyFxlx, taskId));
        //结果集合
        List<CustomOverlay> cusOverlayList = new ArrayList<CustomOverlay>();

        //解析参数
        GeoJsonQuery allGeoQuery = dlhyAnalyseParam.getGeoJsonQuery();// 上传的图形
        if (allGeoQuery == null || allGeoQuery.getGeoJson() == null) {
            System.out.println(String.format("--->overlayBgdc stoped，allGeoQuery or allGeoQuery.getGeoJson is null "));
            return cusOverlayList;
        }

        if(StringUtil.isNullOrEmpty(taskId)) {
            taskId = UUID.randomUUID().toString();
        }
        String analyseType= allGeoQuery.getType().toString();
        String msgStr = String.format("--->overlayBgdc,分析开始!, taskId: %s",taskId);
        System.out.println();
        System.out.println(msgStr);


        if (allGeoQuery.getGeoJson().trim().startsWith("{")) {
            GeoJson geoJson = (GeoJson) JSONObject.parseObject(allGeoQuery.getGeoJson(), GeoJson.class);

            cusOverlayList = new ArrayList<CustomOverlay>();

            // 3.非常重要，逐个地块进行空间叠加分析、分类面积汇总
            List<GeoJsonFeature> feas = geoJson.getFeatures();
            int feaCount=feas.size();
            for (int i = 0; i < feaCount; i++) {
                GeoJsonFeature fea = feas.get(i);

                System.out.println();
                int xh = i+1;
                //步骤1-关键参数，获取TBBH信息，如果无TBBH，则按顺序号生成一个
                Map<String, Object> feaPropers = fea.getProperties();

                //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
                Map<String,Object> feaPropsKeyLowercCase = new HashMap<>();
                feaPropers.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));


                String dkbh = feaPropsKeyLowercCase.get("dkbh") != null ? feaPropsKeyLowercCase.get("dkbh").toString() : String.valueOf(i+10000) ;//DKBH
                if (StringUtil.isNullOrEmpty(dkbh)) {
                    // 不参加叠加运算
                    System.out.println(String.format("--->地块编号DKBH为空, 自动分配地块编号为：%s ","地块"+(xh)));
                    //continue;
                }
                //使用用地红线范围图层中的bz字段
                String hysjnfStr = defaultDlhynfStr;
                String bz_nfStr = feaPropsKeyLowercCase.get("bz") != null ? feaPropsKeyLowercCase.get("bz").toString() : "" ;//BZ
                System.out.println(String.format("--->第 %d / %d 个地块overlayBgdc分析开始,地块编号：%s, bz_nfStr：%s", xh, feaCount, dkbh, bz_nfStr));

                //步骤2-类型筛选
                String fwdm = feaPropsKeyLowercCase.get("fwdm") != null ? feaPropsKeyLowercCase.get("fwdm").toString() : "1";//FWDM
                if("2".equalsIgnoreCase(fwdm)){
                    //对“1与3”类型的地类图斑进行地类还原，“2”类型的图斑跳过
                    //continue;
                }
                //地块面积
                double dkmj = feaPropsKeyLowercCase.get("dkmj") != null ? Double.parseDouble(feaPropsKeyLowercCase.get("dkmj").toString()) : 0.0 ;//DKMJ

                //步骤3-还原数据年度
                if(StringUtil.isNullOrEmpty(bz_nfStr)){
                    System.out.println(String.format("--->该地块的还原数据年度字段BZ为空, 系统将默认还原到最近年度。DKBH为：%s ","地块"+dkbh));
                    //默认还原时间年度;
                    hysjnfStr = defaultDlhynfStr;
                }else{
                    int lengthOfNf = bz_nfStr.length();
                    if(lengthOfNf>4) {
                        hysjnfStr = bz_nfStr.substring(0, 4);
                    }else{
                        hysjnfStr = bz_nfStr;
                    }
                }

                int dlhynf = 2021;//BZ字段指示的地类还原年份
                try {
                    dlhynf = Integer.parseInt(hysjnfStr);
                    if (dlhynf <= 2009) {
                        dlhynf = 2009;
                        hysjnfStr = "2009";
                        System.out.println(String.format("--->******************BZ字段值在数据最小年份2009年以前,统一执行二调标准2009年*****************"));
                    }
                }catch (Exception ex){
                    System.out.println(String.format("--->BZ 字段（年份字符串）不符要求, nf：%s, bz:%s ",hysjnfStr, bz_nfStr));
                    ex.printStackTrace();
                }
                //通过年份找到还原地类图斑的图层名称
                AnalyseTable analyseTable = this.analyseConfig.getDltbAnalyseTableByYear(hysjnfStr);
                if( analyseTable==null){
                    System.out.println();
                    System.out.println(String.format("--->该地块的还原数据年度填写有误或者未配置对应年份的分析数据，请检查。dkbh: %s, nf: %s", dkbh, hysjnfStr));

                    continue;
                }
                System.out.println(String.format("--->该地块的还原数据年度BZ：%s ",hysjnfStr));

                List<AnalyseTable> analyseTablesParams = new ArrayList<AnalyseTable>();
                analyseTablesParams.add(analyseTable);

                /************* 2.上传的地块分为单个地块进行叠加 ***************/
                // 构建单个地块的Feature
                List<GeoJsonFeature> subFeas = new ArrayList<GeoJsonFeature>();
                subFeas.add(fea);
                GeoJson dkGeoJson = new GeoJson();
                dkGeoJson.setType(geoJson.getType());
                dkGeoJson.setFeatures(subFeas);
                String dkJsonStr = JSONObject.toJSONString(dkGeoJson);

                GeoJsonQuery dkQuery = new GeoJsonQuery();
                dkQuery.setDigits(allGeoQuery.getDigits());
                dkQuery.setReturnEllipsoidalArea(allGeoQuery.getReturnEllipsoidalArea());
                dkQuery.setType(allGeoQuery.getType());
                dkQuery.setWkid(allGeoQuery.getWkid());
                dkQuery.setGeoJson(dkJsonStr);

                String jobId = UUID.randomUUID().toString();
                //System.out.println(String.format("--->overlay Dlhy，DKBH: %s, DKMJ: %f, jobId: %s", dkbh, dkmj, jobId));

                //分析参数组装
                AnalyseTaskParam taskParam = new AnalyseTaskParam(analyseType);
                taskParam.setJobId(jobId);
                taskParam.setTaskId(taskId);
                taskParam.setDkbh(dkbh);
                taskParam.setDkmj(dkmj);
                taskParam.setQuery(dkQuery);
                taskParam.setDlhynf(dlhynf);

                //核心代码，提交开展分析分析结果
                CustomOverlay cusOverlay = this.parallelAnalyseService.submitOverlayCustomAnalyse(analyseType,taskParam, analyseTablesParams);
                cusOverlay.setDkbh(dkbh);
                cusOverlay.setPhase(dlhyAnalyseParam.getPhase());

                cusOverlayList.add(cusOverlay);
                System.out.println(String.format("--->第 %d / %d 个地块overlayBgdc分析完毕, 地块编号：%s", xh, feaCount, dkbh));

            }
            System.out.println();
            System.out.println("--->overlayBgdc,所有地块分析完成!");
            System.out.println();

        }

        return cusOverlayList;
    }



    /**
     * 地类还原分析：按地块批量创建线程开展还原分析
     *
     * @param taskId   项目编号
     * @param dlhyAnalyseParam   地类还原分析参数
     * @return
     */
    public List<CustomOverlay> overlayDlhyEx(String taskId, DlhyAnalyseParam dlhyAnalyseParam) {

        String dlhyFxlx = dlhyAnalyseParam.getType();
        System.out.println(String.format("--->overlayDlhyEx，dlhyFxlx: %s, taskId: %s",dlhyFxlx, taskId));

        //结果集合
        List<CustomOverlay> cusOverlayList = new ArrayList<CustomOverlay>();
        //解析参数
        GeoJsonQuery allGeoQuery = dlhyAnalyseParam.getGeoJsonQuery();// 上传的图形
        if (allGeoQuery == null || allGeoQuery.getGeoJson() == null) {
            System.out.println(String.format("--->overlayDlhyEx stoped，allGeoQuery or allGeoQuery.getGeoJson is null "));
            return cusOverlayList;
        }
        if(StringUtil.isNullOrEmpty(taskId)) {
            taskId = UUID.randomUUID().toString();
        }

        List<AnalyseTaskParamEx> taskParams= new ArrayList<AnalyseTaskParamEx>();

        String analyseType = allGeoQuery.getType().toString();
        String msgStr = String.format("--->overlayDlhyEx,分析开始!, taskId: %s",taskId);
        System.out.println();
        System.out.println(msgStr);

        if (allGeoQuery.getGeoJson().trim().startsWith("{")) {
            GeoJson geoJson = (GeoJson) JSONObject.parseObject(allGeoQuery.getGeoJson(), GeoJson.class);

            cusOverlayList = new ArrayList<CustomOverlay>();

            // 3.非常重要，逐个地块进行后台空间叠加分析、面积归类汇总等操作
            List<GeoJsonFeature> feas = geoJson.getFeatures();
            int feaCount = feas.size();
            for (int i = 0; i < feaCount; i++) {
                GeoJsonFeature fea = feas.get(i);

                System.out.println();
                //获取TBBH信息
                Map<String, Object> feaPropers = fea.getProperties();

                //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
                Map<String,Object> feaPropsKeyLowercCase = new HashMap<>();
                feaPropers.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));


                String dkbh = feaPropsKeyLowercCase.get("tbbh") != null ? feaPropsKeyLowercCase.get("tbbh").toString() : String.valueOf(i + 10000);//TBBH
                if (StringUtil.isNullOrEmpty(dkbh)) {
                    // 不参加叠加运算
                    System.out.println(String.format("--->地块编号DKBH或TBBH为空, 自动分配地块编号为：%s ", "地块" + (i + 1)));
                    //continue;
                }
                //还原数据年度
                String dlhyYearStr = defaultDlhynfStr;
                //变化图斑图层的还原时间年度HYSJND
                String hysjndStr = feaPropsKeyLowercCase.get("hysjnd") != null ? feaPropsKeyLowercCase.get("hysjnd").toString() : "";//HYSJND
                System.out.println(String.format("--->第 %d / %d 个地块overlayDlhy分析开始,地块编号：%s, 还原时间年度：%s", i + 1, feaCount, dkbh, hysjndStr));

                //变化代码BHDM
                String bhdm = feaPropsKeyLowercCase.get("bhdm") != null ? feaPropsKeyLowercCase.get("bhdm").toString() : "1";//BHDM
                if ("2".equalsIgnoreCase(bhdm)) {
                    //对“1与3”类型的地类图斑进行地类还原，“2”类型的图斑跳过
                    //continue;
                }

                //地块面积
                double dkmj = feaPropsKeyLowercCase.get("tbmj") != null ? Double.parseDouble(feaPropsKeyLowercCase.get("tbmj").toString()) : 0.0;//TBMJ

                //为了测试，新增字段，后期注释改行代码。王强 2023年2月
                //String hysjndStr2 = feaPropers.get("HYSJND2") != null ? feaPropers.get("HYSJND2").toString() : " " ;
                //用地红线范围
                //String hysjndStr = feaPropers.get("KCDJRQ") != null ? feaPropers.get("KCDJRQ").toString() : "" ;
                if (StringUtil.isNullOrEmpty(hysjndStr)) {
                    System.out.println(String.format("--->该地块的还原数据年度字段HYSJND为空, 系统将默认还原到最近年度。DKBH为：%s ", "地块" + dkbh));
                    //默认还原时间年度;
                    dlhyYearStr = defaultDlhynfStr;
                } else {
                    System.out.println("--->overlayDlhy, hysjndStr: " + hysjndStr);
                    try {
                        Date hysjndDate = DateUtil.parseSTDDateStr(hysjndStr);
                        dlhyYearStr = DateUtil.getYear(hysjndDate);
                    } catch (ParseException e) {
                        e.printStackTrace();
                    }
                }

                System.out.println(String.format("--->该地块的还原数据年度HYSJND：%s ", dlhyYearStr));
                //还原时间年度,正整数
                int dlhynf = Integer.parseInt(dlhyYearStr);
                if (dlhynf <= 2009) {
                    System.out.println(String.format("--->*****************************地类还原的年份小于数据库最小年份2009，统一执行2009二调标准******************************"));
                    dlhynf = 2009;
                    dlhyYearStr = "2009";
                }
                //通过年份year查询找到地类还原对应的DLTB的图层名称
                AnalyseTable analyseTable = this.analyseConfig.getDltbAnalyseTableByYear(dlhyYearStr);
                if (analyseTable == null) {
                    System.out.println();
                    System.out.println(String.format("--->*****************************skip overlayDlhy, taskId： %s **********************************", taskId));
                    System.out.println(String.format("--->该地块的还原数据年度HYSJND填写有误或者系统未配置对应年份的分析数据，请检查。dkbh: %s, hysjnd: %s", dkbh, dlhyYearStr));

                    continue;
                }


                /************* 2.上传的地块分为单个地块进行叠加 ***************/
                // 构建单个地块的Feature
                List<GeoJsonFeature> subFeas = new ArrayList<GeoJsonFeature>();
                subFeas.add(fea);

                GeoJson dkGeoJson = new GeoJson();
                dkGeoJson.setType(geoJson.getType());
                dkGeoJson.setFeatures(subFeas);
                String dkJsonStr = JSONObject.toJSONString(dkGeoJson);

                GeoJsonQuery dkQuery = new GeoJsonQuery();
                dkQuery.setDigits(allGeoQuery.getDigits());
                dkQuery.setReturnEllipsoidalArea(allGeoQuery.getReturnEllipsoidalArea());
                dkQuery.setType(allGeoQuery.getType());
                dkQuery.setWkid(allGeoQuery.getWkid());
                dkQuery.setGeoJson(dkJsonStr);

                String jobId = UUID.randomUUID().toString();
                //System.out.println(String.format("--->overlay Dlhy: %s，DKBH: %s, DKMJ: %f", jobId, dkbh, dkmj));

                //分析参数组装
                AnalyseTaskParamEx taskParam = new AnalyseTaskParamEx(analyseType);
                taskParam.setTaskId(taskId);
                taskParam.setJobId(jobId);
                taskParam.setDkbh(dkbh);
                taskParam.setDkmj(dkmj);
                taskParam.setQuery(dkQuery);
                taskParam.setDlhynf(dlhynf);
                taskParam.setAnalyseTable(analyseTable);

                taskParams.add(taskParam);
            }

            //核心代码，提交开展分析分析结果
            cusOverlayList = this.parallelAnalyseService.submitOverlayAnalyseByDK(analyseType,taskParams);


            System.out.println();
            System.out.println("--->overlayDlhyEx,所有地块地类还原分析完成!");
            System.out.println();

        }

        return cusOverlayList;
    }

    /**
     * 图斑批量创建线程开展变更调查分析
     *
     * @param taskId
     * @param dlhyAnalyseParam
     * @return
     */
    public List<CustomOverlay> overlayBgdcEx(String taskId, DlhyAnalyseParam dlhyAnalyseParam) {

        String dlhyFxlx = dlhyAnalyseParam.getType();
        System.out.println(String.format("--->overlayBgdcEx started，dlhyFxlx: %s, taskId: %s", dlhyFxlx, taskId));

        //结果集合
        List<CustomOverlay> cusOverlayList = null;

        //解析参数
        GeoJsonQuery allGeoQuery = dlhyAnalyseParam.getGeoJsonQuery();// 上传的图形
        if (allGeoQuery == null || allGeoQuery.getGeoJson() == null) {
            System.out.println(String.format("--->overlayBgdcEx stoped，allGeoQuery or allGeoQuery.getGeoJson is null "));
            return cusOverlayList;
        }

        if(StringUtil.isNullOrEmpty(taskId)) {
            taskId = UUID.randomUUID().toString();
        }
        String analyseType= allGeoQuery.getType().toString();
        String msgStr = String.format("--->overlayBgdcEx,分析开始!, taskId: %s",taskId);
        System.out.println();
        System.out.println(msgStr);

        //以地块为单位组织的分析参数集合
        List<AnalyseTaskParamEx> taskParams = new ArrayList<AnalyseTaskParamEx>();

        if (allGeoQuery.getGeoJson().trim().startsWith("{")) {
            GeoJson geoJson = (GeoJson) JSONObject.parseObject(allGeoQuery.getGeoJson(), GeoJson.class);

            // 3.非常重要，逐个地块进行空间叠加分析、分类面积汇总
            List<GeoJsonFeature> feas = geoJson.getFeatures();
            int feaCount=feas.size();
            for (int i = 0; i < feaCount; i++) {
                GeoJsonFeature fea = feas.get(i);

                System.out.println();
                int xh = i + 1;
                //步骤1-关键参数，获取TBBH信息，如果无TBBH，则按顺序号生成一个
                Map<String, Object> feaPropers = fea.getProperties();

                //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
                Map<String,Object> feaPropsKeyLowercCase = new HashMap<>();
                feaPropers.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));


                String dkbh = feaPropsKeyLowercCase.get("dkbh") != null ? feaPropsKeyLowercCase.get("dkbh").toString() : String.valueOf(i + 10000);//DKBH
                if (StringUtil.isNullOrEmpty(dkbh)) {
                    // 不参加叠加运算
                    System.out.println(String.format("--->地块编号DKBH为空, 自动分配地块编号为：%s ", "地块" + (xh)));
                    //continue;
                }
                //使用用地红线范围图层中的bz字段
                String hysjnfStr = defaultDlhynfStr;
                String bz_nfStr = feaPropsKeyLowercCase.get("bz") != null ? feaPropsKeyLowercCase.get("bz").toString() : "";//BZ
                System.out.println(String.format("--->第 %d / %d 个地块overlayBgdc分析开始,地块编号：%s, bz_nfStr：%s", xh, feaCount, dkbh, bz_nfStr));

                //步骤2-类型筛选
                String fwdm = feaPropsKeyLowercCase.get("fwdm") != null ? feaPropsKeyLowercCase.get("fwdm").toString() : "1";//FWDM
                if ("2".equalsIgnoreCase(fwdm)) {
                    //对“1与3”类型的地类图斑进行地类还原，“2”类型的图斑跳过
                    //continue;
                }
                //地块面积
                double dkmj = feaPropsKeyLowercCase.get("dkmj") != null ? Double.parseDouble(feaPropsKeyLowercCase.get("dkmj").toString()) : 0.0;//DKMJ

                //步骤3-还原数据年度
                if (StringUtil.isNullOrEmpty(bz_nfStr)) {
                    System.out.println(String.format("--->该地块的还原数据年度字段BZ为空, 系统将默认还原到最近年度。DKBH为：%s ", "地块" + dkbh));
                    //默认还原时间年度;
                    hysjnfStr = defaultDlhynfStr;
                } else {
                    int lengthOfNf = bz_nfStr.length();
                    if (lengthOfNf > 4) {
                        hysjnfStr = bz_nfStr.substring(0, 4);
                    } else {
                        hysjnfStr = bz_nfStr;
                    }
                }

                int dlhynf = 2021;//BZ字段指示的地类还原年份
                try {
                    dlhynf = Integer.parseInt(hysjnfStr);
                    if (dlhynf <= 2009) {
                        dlhynf = 2009;
                        hysjnfStr = "2009";
                        System.out.println(String.format("--->******************BZ字段值在数据最小年份2009年以前,统一执行二调标准2009年*****************"));
                    }
                } catch (Exception ex) {
                    System.out.println(String.format("--->BZ 字段（年份字符串）不符要求, nf：%s, bz:%s ", hysjnfStr, bz_nfStr));
                    ex.printStackTrace();
                }
                //通过年份找到还原地类图斑的图层名称
                AnalyseTable analyseTable = this.analyseConfig.getDltbAnalyseTableByYear(hysjnfStr);
                if (analyseTable == null) {
                    System.out.println();
                    System.out.println(String.format("--->该地块的还原数据年度填写有误或者未配置对应年份的分析数据，请检查。dkbh: %s, nf: %s", dkbh, hysjnfStr));

                    continue;
                }

                System.out.println(String.format("--->该地块的还原数据年度BZ：%s ", hysjnfStr));

                /************* 2.上传的地块分为单个地块进行叠加 ***************/
                // 构建单个地块的Feature
                List<GeoJsonFeature> subFeas = new ArrayList<GeoJsonFeature>();
                subFeas.add(fea);
                GeoJson dkGeoJson = new GeoJson();
                dkGeoJson.setType(geoJson.getType());
                dkGeoJson.setFeatures(subFeas);
                String dkJsonStr = JSONObject.toJSONString(dkGeoJson);

                GeoJsonQuery dkQuery = new GeoJsonQuery();
                dkQuery.setDigits(allGeoQuery.getDigits());
                dkQuery.setReturnEllipsoidalArea(allGeoQuery.getReturnEllipsoidalArea());
                dkQuery.setType(allGeoQuery.getType());
                dkQuery.setWkid(allGeoQuery.getWkid());
                dkQuery.setGeoJson(dkJsonStr);

                String jobId = UUID.randomUUID().toString();
                //System.out.println(String.format("--->overlay Dlhy，DKBH: %s, DKMJ: %f, jobId: %s", dkbh, dkmj, jobId));

                //分析参数组装
                AnalyseTaskParamEx taskParam = new AnalyseTaskParamEx(analyseType);
                taskParam.setJobId(jobId);
                taskParam.setTaskId(taskId);
                taskParam.setDkbh(dkbh);
                taskParam.setDkmj(dkmj);
                taskParam.setQuery(dkQuery);
                taskParam.setDlhynf(dlhynf);
                taskParam.setAnalyseTable(analyseTable);

                taskParams.add(taskParam);
            }

             //核心代码，提交开展分析分析结果
            cusOverlayList = this.parallelAnalyseService.submitOverlayAnalyseByDK(analyseType,taskParams);

            System.out.println();
            System.out.println("--->overlayBgdcEx,所有地块分析完成!");
            System.out.println();

        }

        return cusOverlayList;
    }

    /**
     *
     * @param stgeoFeatureMap  StgeoFeature包含属性集合和图形wkt
     * @param properDefs  属性结构定义（包括属性名和类型名）
     * @param filePath    输出shp路径
     * @throws SchemaException
     * @throws IOException
     */
    @Override
    public void saveStgeoFeatureAsNewSHP(String taskId, int wkid, Map<String,StgeoFeature> stgeoFeatureMap, Map<String, String> properDefs,
                                         String filePath) throws SchemaException, IOException {
        String formatmsg = String.format("--->saveStgeoFeatureAsNewSHP start, taskId: %s, stgeoFeatureMap: %d", taskId,stgeoFeatureMap.size());
        System.out.println();
        System.out.println(formatmsg);
        logger.info(formatmsg);

        /************** 第一步 Polygon转geojson *****************/

        System.out.println("**************第一步 Polygon转geojson *****************");

        List<StgeoField> fieldList= new ArrayList<StgeoField>();
        // 业务属性字段
        String ywFieldsStr = "";
        if (properDefs != null && properDefs.size() > 0) {
            StringBuilder sb = new StringBuilder();
            //Set<String> fieldSet=  properDefs.keySet();
            int xh=0;
            for (Map.Entry<String,String> ent: properDefs.entrySet()) {
                xh++;
                String fieldName = ent.getKey();
                String fieldType = ent.getValue();
                //字段定义1
                sb.append(fieldName + ":" + fieldType);
                sb.append(",");
                String ss= String.format("--->name:%s, value: %s",fieldName,fieldType);
                System.out.println(ss);

                //字段定义2
                StgeoField stgeoField = new StgeoField(xh);
                stgeoField.setName(fieldName);
                stgeoField.setType(fieldType);
                stgeoField.setAlias(fieldName);
                fieldList.add(stgeoField);
            }
            sb.setCharAt(sb.length() - 1, ',');
            ywFieldsStr = sb.toString();
        } else {
            ywFieldsStr = "ffid:String," + "tbbh:String," +"bz:String";
        }

        //字段按xh进行排序
        Collections.sort(fieldList);

        // 新建
        final SimpleFeatureType TYPE = DataUtilities.createType("Link", "geometry:Polygon," + ywFieldsStr);
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
        List<SimpleFeature> features = new ArrayList<>();
        // 遍历所有图形
        for (Map.Entry<String, StgeoFeature> ent : stgeoFeatureMap.entrySet()) {
            String id = ent.getKey();// key
            StgeoFeature stgeoFea = ent.getValue();//value

            Map<String,Object> feaPropers = stgeoFea.getProperties();// 属性

            //将要素属性的key全部转为小写，否则oracle和postgresql数据库返回的结果会有差异
            Map<String,Object> feaPropsKeyLowercCase = new HashMap<>();
            feaPropers.forEach((key,value) -> feaPropsKeyLowercCase.put(key.toLowerCase(), value));


            String xmmc = feaPropsKeyLowercCase.get("xmmc").toString();//XMMC
            String qswdmc = feaPropsKeyLowercCase.get("qsdwmc").toString();//QSDWMC
            String tbbh = feaPropsKeyLowercCase.get("tbbh").toString();//TBBH
            String dlbm = feaPropsKeyLowercCase.get("dlbm").toString();//DLBM
            String dlmc = feaPropsKeyLowercCase.get("dlmc").toString();//DLMC
            String bz = feaPropsKeyLowercCase.get("bz").toString();//BZ
            double tbmj = StringUtil.parseDouble(feaPropsKeyLowercCase.get("tbmj").toString(),"0.0");//TBMJ
            String bhdm = feaPropsKeyLowercCase.get("bhdm").toString();//BHDM
            String hyyy = feaPropsKeyLowercCase.get("hyyy").toString();//HYYY
            String hysjnd = feaPropsKeyLowercCase.get("hysjnd").toString();//HYSJND
            String hyzmcl = feaPropsKeyLowercCase.get("hyzmcl").toString();//HYZMCL
            String pzzmcl = feaPropsKeyLowercCase.get("pzzmcl").toString();//PZZMCL
            String pzwh = feaPropsKeyLowercCase.get("pzwh").toString();//PZWH
            String hysjnd2 = feaPropsKeyLowercCase.get("hysjnd2").toString();//HYSJND2

            Geometry geom = stgeoFea.getGeometry();// 图形
            String geometryType= geom.getGeometryType();
            String  wkt = JTSGeometryWKTUtil.jtsGeom2wkt(geom);
            String wkt2 = geom.toText();

            // 1-2转换图形
            List<Polygon> polygonList = new ArrayList<Polygon>();
            int idxOfWktType = wkt.indexOf("(");
            String wktType = wkt.substring(0, idxOfWktType).trim();
            if ("MULTIPOLYGON".equalsIgnoreCase(wktType)) {
                MultiPolygon multiPolygon = JTSGeometryWKTUtil.createMulPolygonByWKT(wkt);
                List<Polygon> polygons = JTSGeometryWKTUtil.multipolygon2Polygons(multiPolygon);
                for (Polygon polygon : polygons) {
                    polygonList.add(polygon);
                }
            } else if ("POLYGON".equalsIgnoreCase(wktType)) {
                Polygon polygon = JTSGeometryWKTUtil.createPolygonByWKT(wkt);
                polygonList.add(polygon);
            }

            for (Polygon polygon : polygonList) {
                // Feature
                // String uuid = UUID.randomUUID().toString();
                featureBuilder.add(polygon);
                for(int j=0; j<fieldList.size(); j++){
                    StgeoField field= fieldList.get(j);
                    int xh = field.getOrder();
                    String fieldName= field.getName();
                    switch (fieldName.toLowerCase()){
                        case "xmmc":
                            featureBuilder.add(xmmc);//uuid
                            break;
                        case "qswdmc":
                            featureBuilder.add(qswdmc);
                            break;
                        case "tbbh":
                            featureBuilder.add(tbbh);
                            break;
                        case "dldm":
                            featureBuilder.add(dlbm);
                            break;
                        case "dlmc":
                            featureBuilder.add(dlmc);
                            break;
                        case "bz":
                            featureBuilder.add(bz);
                            break;

                        case "tbmj":
                            featureBuilder.add(tbmj);
                            break;
                        case "bhdm":
                            featureBuilder.add(bhdm);
                            break;
                        case "hyyy":
                            featureBuilder.add(hyyy);
                            break;
                        case "hysjnd":
                            featureBuilder.add(hysjnd);
                            break;
                        case "hyzmcl":
                            featureBuilder.add(hyzmcl);
                            break;
                        case "pzzmcl":
                            featureBuilder.add(pzzmcl);
                            break;

                        case "pzwh":
                            featureBuilder.add(pzwh);
                            break;
                        case "hysjnd2":
                            featureBuilder.add(hysjnd2);
                            break;
                    }
                }

                SimpleFeature feature = featureBuilder.buildFeature(null);
                features.add(feature);
            }
        }
        // 写入
        StringWriter writer = new StringWriter();
        SimpleFeatureCollection feaCollection = new ListFeatureCollection(TYPE, features);
        FeatureJSON fjson = new FeatureJSON();
        fjson.writeFeatureCollection(feaCollection, writer);

        // 导出geojson文件
        String geojson = writer.toString();
        System.out.println();
        System.out.println("--->featurecollection geojson: %s " + geojson);

        /************** 第二步 geojson保存为SHP *****************/
        System.out.println();
        System.out.println("**************第二步 geojson保存为SHP *****************");
        File shpFile = new File(filePath);

        String fields2= JSONArray.toJSONString(fieldList);

        // 根据geojson生成shapefile
        //4490 经纬度
        String crs_wkt = CrsUtil.getWKT(wkid);
        String geometryType = "esriGeometryPolygon";
        String fields = "[{\"name\":\"ffid\",\"type\":\"esriFieldTypeString\",\"alias\":\"ffid\"},{\"name\":\"tbbh\",\"type\":\"esriFieldTypeString\",\"alias\":\"tbbh\"},{\"name\":\"bz\",\"type\":\"esriFieldTypeString\",\"alias\":\"bz\"}]";

        try {
            GeoJson2Shapefile.createShapefile1(shpFile, geojson, crs_wkt, geometryType.toLowerCase(), fields);
        } catch (IOException | FactoryException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void saveDlhyListAsNewSHP(String taskId, int wkid, List<DlhyEntity> dlhyEntities, String filePath) throws SchemaException, IOException {
        String formatmsg = String.format("--->saveDlhyListAsNewSHP start, taskId:%s, filePath: %s, dlhyEntities size: %d", taskId, filePath,dlhyEntities.size());
        System.out.println(formatmsg);
        logger.info(formatmsg);

        // 业务属性字段
        String ywFieldsStr = "TASKID:String," + "DKBH:String," + "DLBM:String," + "DLMC:String,"+"FXLX:String,"+ "DJMJ:Double,"+ "TKMJ:Double,"+  "KCMJ:Double,"+ "KCHMJ:Double,"+"BZ:String";

        System.out.println();
        System.out.println("**************第一步 创建SHP文件 *****************");
        // 新建Shape文件
        final SimpleFeatureType TYPE = DataUtilities.createType("Link", "geometry:Polygon," + ywFieldsStr);
        SimpleFeatureBuilder featureBuilder = new SimpleFeatureBuilder(TYPE);
        List<SimpleFeature> features = new ArrayList<>();

        int numOfEntity = dlhyEntities.size();
        for(int i=0; i<numOfEntity; i++){
            int xh = i+1;

            DlhyEntity dlhyEntity = dlhyEntities.get(i);
            String dkbh = dlhyEntity.getDkbh();
            String dlbm = dlhyEntity.getDlbm();
            String dlmc = dlhyEntity.getDlmc();
            String fxlx = dlhyEntity.getFxlx();//分析类型bgdc、dlhy
            double djmj = dlhyEntity.getDjmj();//相交几何面积
            double tkmj = dlhyEntity.getTkmj();//田坎面积
            double kcmj = dlhyEntity.getKcmj();//扣除面积，包括现状地物和零星地物
            double kchmj = dlhyEntity.getKchmj();//地类净面积

            String geomText = dlhyEntity.getGeomText();
            //geomtext转换为Polygon
            //JSONObject geomObject = JSON.parseObject(geomText);
            GeoJsonGeometry geom = JSON.parseObject(geomText, GeoJsonGeometry.class);

            //下面的代码逻辑是有问题的。
            //叠加分析回来的结果图形如果是个多面体，则多个图形具有相同的属性值和面积。这是有问题的
            int numOfPolygon = 0;
            List<Polygon> polygonList = JTSGeometryWKTUtil.geoJsonGeometry2Polygon(geom);
            for (Polygon polygon : polygonList) {
                // Feature
                featureBuilder.add(polygon);

                numOfPolygon++;

                //很重要，根据几何面积的比例进行属性面积重新分摊
                Double area =Math.abs(polygon.getArea());
                Double percent=0.0;
                if(djmj != 0){
                    Double percentOfMj = area/djmj;
                    percent =  percentOfMj < 1.0 ? percentOfMj : 1.0;//面积分摊比例，最大为1.0
                }else {
                    percent=0.0;
                }

                //String msg = String.format("--->xh: %d, builder polygon, taskId：%s, dkbh:%s, num:%d, dlbm:%s,dlmc:%s, fxlx:%s, djmj: %f, area:%f, percent: %f ", xh, taskId, dkbh, numOfPolygon, dlbm, dlmc, fxlx, djmj, area, percent);
                //System.out.println(msg);

                featureBuilder.add(taskId);//任务编号
                featureBuilder.add(dkbh);//地块编号
                featureBuilder.add(dlbm);//地类编码
                featureBuilder.add(dlmc);//地类名称
                featureBuilder.add(fxlx);//分析类型，bgdc和dlhy
                featureBuilder.add(djmj * percent);//图形几何面积
                featureBuilder.add(tkmj * percent);//田坎面积
                featureBuilder.add(kcmj * percent);//扣除面积
                featureBuilder.add(kchmj * percent);//地类净面积
                featureBuilder.add("test");//备注

                SimpleFeature feature = featureBuilder.buildFeature(null);
                features.add(feature);
            }
        }

        // 写入
        StringWriter writer = new StringWriter();
        SimpleFeatureCollection feaCollection = new ListFeatureCollection(TYPE, features);
        FeatureJSON fjson = new FeatureJSON();
        fjson.writeFeatureCollection(feaCollection, writer);

        // 导出geojson文件
        String geojson = writer.toString();
        //System.out.println();
        //System.out.println("--->featurecollection geojson: %s " + geojson);

        /************** 第二步 geojson保存为SHP *****************/
        System.out.println();
        System.out.println("**************第二步 geojson保存为SHP *****************");
        File shpFile = new File(filePath);

        // 根据geojson生成shapefile
        //4490 经纬度
        String crs_wkt = CrsUtil.getWKT(wkid);
        String geometryType = "esriGeometryPolygon";
        String fields = "[" +
                "{\"name\":\"TASKID\",\"type\":\"esriFieldTypeString\",\"alias\":\"TASKID\"}," +
                "{\"name\":\"DKBH\",\"type\":\"esriFieldTypeString\",\"alias\":\"DKBH\"}," +
                "{\"name\":\"DLBM\",\"type\":\"esriFieldTypeString\",\"alias\":\"DLBM\"}," +
                "{\"name\":\"DLMC\",\"type\":\"esriFieldTypeString\",\"alias\":\"DLMC\"}," +
                "{\"name\":\"FXLX\",\"type\":\"esriFieldTypeString\",\"alias\":\"FXLX\"}," +
                "{\"name\":\"DJMJ\",\"type\":\"esriFieldTypeDouble\",\"alias\":\"DJMJ\"}," +
                "{\"name\":\"TKMJ\",\"type\":\"esriFieldTypeDouble\",\"alias\":\"TKMJ\"}," +
                "{\"name\":\"KCMJ\",\"type\":\"esriFieldTypeDouble\",\"alias\":\"KCMJ\"}," +
                "{\"name\":\"KCHMJ\",\"type\":\"esriFieldTypeDouble\",\"alias\":\"KCHMJ\"}," +
                "{\"name\":\"BZ\",\"type\":\"esriFieldTypeString\",\"alias\":\"BZ\"}" +
                "]";

        try {
            GeoJson2Shapefile.createShapefile1(shpFile, geojson, crs_wkt, geometryType.toLowerCase(), fields);
        } catch (IOException | FactoryException e) {
            e.printStackTrace();
        }

    }


}
